﻿/*
 * Created by SharpDevelop.
 * User: lin
 * Date: 2019/4/18
 * Time: 22:22
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace supersocketest1
{
	/// <summary>
	/// Description of FormClient.
	/// </summary>
	public partial class FormClient : Form
	{
		
		/// <summary>
/// 委托接收服务端发送的数据
/// </summary>
/// <param name="receiveBuffer"></param>
public delegate void ReceiveHandle(byte[] receiveBuffer);
		/// <summary>
		/// 接收服务端发送的数据事件
		/// </summary>
		public event ReceiveHandle ReceiveDataEvent;
		/// <summary>
		/// 客户端连接
		/// </summary>
		TcpClient tcpClient;
		ManualResetEvent manualWait = new ManualResetEvent(false);
		/// <summary>
		/// 是否已连接
		/// </summary>
		bool isConnect = false;
		/// <summary>
		/// 服务端与客户端send、receive所使用的流
		/// </summary>
		NetworkStream networkStream;
		/// <summary>
		/// 接收线程
		/// </summary>
		Thread receiveThread;
		/// <summary>
		/// 服务器地址和端口 如 192.168.0.23:3456
		/// </summary>
		string serverIpAndPort = string.Empty;
		
		public FormClient()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			
			//
			// TODO: Add constructor code after the InitializeComponent() call.
			//
		}
		
		private void FormClient_ReceiveDataEvent(byte[] buffer)
		{
			string message = serverIpAndPort + "说 " + Encoding.GetEncoding("gbk").GetString(buffer);
			this.Invoke(new MethodInvoker(() => {
				rtxtInfo.AppendText(message + "\n");
			}));
		}
		/// <summary>
		/// 异步连接服务端
		/// </summary>
		/// <param name="serverIP">服务端IP地址</param>
		/// <param name="port">服务端端口</param>
		/// <returns></returns>
		private bool ConnectServer(string serverIP, int port)
		{
			isConnect = false;
			manualWait.Reset();
			tcpClient.BeginConnect(serverIP, port, new AsyncCallback(RequestCallback), tcpClient);
			if (manualWait.WaitOne(30000, false)) {
				if (isConnect) {
					serverIpAndPort = string.Format("{0}:{1}", serverIP, port);
					networkStream = tcpClient.GetStream();
					return true;
				}
				return false;
			} else {
				throw new Exception("回调函数未正常返回，请确认超时参数正确");
			}
		}
		/// <summary>
		/// 异步连接回调函数
		/// </summary>
		/// <param name="asyncResult"></param>
		private void RequestCallback(IAsyncResult asyncResult)
		{
			isConnect = false;
			try {
			//manualWait.Set();
				TcpClient client = asyncResult.AsyncState as TcpClient;
				if (client != null) {
					client.EndConnect(asyncResult);
					isConnect = true;
				}
			} catch (Exception ex) {
				isConnect = false;
				MessageBox.Show("连接服务器出现异常：" + ex.Message, "尝试连接服务器");
			} finally {
				manualWait.Set();
			}
		}
		private void ReceiveProcess()
		{
			try {
				while (isConnect) {
					if (networkStream != null && networkStream.CanRead) {
						//冲刷，强制刷新缓冲区，如果不调用Flush函数，接收的内容将一直停留在缓冲区。Flush函数就是从缓冲区拿到数据
						networkStream.Flush();
						byte[] buffer = new byte[10240];
						//networkStream.ReadTimeout = 10000;
						int byteCount = networkStream.Read(buffer, 0, buffer.Length);
						byte[] destBuffer = new byte[byteCount];
						Array.Copy(buffer, destBuffer, byteCount);
						if (ReceiveDataEvent != null) {
							ReceiveDataEvent(destBuffer);
						}
				//string message = serverIpAndPort + "说 " + Encoding.GetEncoding("gbk").GetString(buffer);
				//this.Invoke(new MethodInvoker(() =>
				//{
				//    rtxtInfo.AppendText(message + "\n");
				//}));
					}
					Thread.Sleep(10);
				}
			} catch (Exception ex) {
				isConnect = false;
				MessageBox.Show(ex.Message, "读取接收数据出错");
			}
		}
		
		
		void BtnConnectClick(object sender, EventArgs e)
		{
			if (isConnect) {
				MessageBox.Show("已连接到服务端");
				return;
			}
			string ipAddress = txtIP.Text;
			int port = int.Parse(txtPort.Text);
			tcpClient = new TcpClient();
			try {
				serverIpAndPort = string.Empty;
				bool connectSuccess = ConnectServer(ipAddress, port);
				if (connectSuccess) {
					rtxtInfo.AppendText(string.Format("已连接到服务器，服务器IP：{0},端口：{1}\n", ipAddress, port));
//订阅服务端发送过来的数据的事件
					ReceiveDataEvent += FormClient_ReceiveDataEvent;
					receiveThread = new Thread(ReceiveProcess);
					receiveThread.IsBackground = true;
					receiveThread.Start();
				} else {
//MessageBox.Show("连接服务端失败");
				}
			} catch (Exception ex) {
				MessageBox.Show(ex.Message, "连接失败");
			}
	
		}
		void BtnDisconnectClick(object sender, EventArgs e)
		{
			isConnect = false;
			try {
				if (tcpClient != null) {
					tcpClient.Close();
				}
				if (networkStream != null) {
					networkStream.Close();
				}
			} catch (Exception ex) {
				MessageBox.Show(ex.Message, "关闭连接出错");
			}
	
		}
		void BtnSendClick(object sender, EventArgs e)
		{
			if (!isConnect) {
				MessageBox.Show("请先连接服务端！", "提示");
				return;
			}
			if (rtxtSendMessage.Text.Length == 0) {
				MessageBox.Show("请输入发送内容！", "提示");
				rtxtSendMessage.Focus();
				return;
			}
			//SuperSocket默认发送约束为结尾是： \r\n
			byte[] buffer = Encoding.GetEncoding("gbk").GetBytes(rtxtSendMessage.Text + "\r\n");
			try {
				networkStream.WriteTimeout = 100;
				if (networkStream.CanWrite) {
					networkStream.Write(buffer, 0, buffer.Length);
				}
			} catch (Exception ex) {
				isConnect = false;
				MessageBox.Show(ex.Message, "发送数据出错");
			}
	
		}
	}
}
